package com.henushang.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;

public class HttpUtil {

    private static Log log = LogFactory.getLog(HttpUtil.class);
    /**
     * get Url Content
     * 
     * @param urlStr
     * @return
     */
    public static String getHttpUrlContent(String urlStr, String encoding) {
        return getHttpUrlContent(urlStr, encoding, false, null);
    }

    
    /**
     * get方式请求http，并且可以设置超时时间，若不设置，则为默认值 0
     * @param url
     * @param timeOutMilliSec
     * @return
     */
    public static byte[] getHttpUrlContent(String url, Integer timeOutMilliSec) {
        if (timeOutMilliSec == null) {
            return getHttpUrlContent(url);
        }
        HttpClient httpClient = new DefaultHttpClient();
        httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeOutMilliSec);
        return getHttpUrlContent(url, httpClient);
    }
    
    /**
     * get方式请求http
     * @param url
     * @return
     */
    public static byte[] getHttpUrlContent(String url) {
        HttpClient httpClient = new DefaultHttpClient();
        return getHttpUrlContent(url, httpClient);
    }
    
    private static byte[] getHttpUrlContent(String url, HttpClient httpClient) {
        HttpGet http = new HttpGet(url);
        
        HttpResponse response = null;
        InputStream inputStream = null;
        try {
            response = httpClient.execute(http);
            if (response.getStatusLine().getStatusCode() != 200) {
                log.error("response status error:"+response.getStatusLine().getStatusCode());
                return new byte[0];
            }
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                inputStream = entity.getContent();
                byte[] c_buf = new byte[8192];
                int len = inputStream.read(c_buf, 0, 8192);
                byte[] result = new byte[0];
                int total = 0;
                while (len > 0) {
                    total += len;
                    byte[] old_result = result;
                    result = new byte[total];
                    if (old_result.length > 0) {
                        System.arraycopy(old_result, 0, result, 0, total - len);
                    }
                    System.arraycopy(c_buf, 0, result, total - len, len);
                    len = inputStream.read(c_buf, 0, 8192);
                }
                return result;
            }
        } catch (ClientProtocolException e) {
            log.error(e.getMessage(),e);
        } catch (IOException e) {
            log.error(e.getMessage(),e);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error(e.getMessage(),e);
            }
        }
        return new byte[0];
    }
    
    public static String getHttpUrlContent(String urlStr, String encoding,
            boolean isPost, String postBody, Map requestProperty) {
        URL url = null;
        HttpURLConnection conn = null;
        try {
            url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            // 设置request header
            if (requestProperty != null) {
                for (Iterator it = requestProperty.keySet().iterator(); it
                        .hasNext();) {
                    String key = (String) it.next();
                    conn.setRequestProperty(key,
                            (String) requestProperty.get(key));
                }
            }
            // conn.setInstanceFollowRedirects(false);
            // post方法
            if (isPost) {
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
            }
            conn.setConnectTimeout(10000);
            conn.setReadTimeout(10000);
            // 建立连接
            conn.connect();
            if (isPost) {
                OutputStream out = conn.getOutputStream();
                out.write(postBody.getBytes(encoding));
                out.flush();
            }
            InputStream is = null;
            try {
                is = conn.getInputStream();
            } catch (IOException ex) {
                is = conn.getErrorStream();
            }
            BufferedReader breader = new BufferedReader(new InputStreamReader(
                    is, encoding));
            char[] c_buf = new char[8192];
            StringBuffer buf = new StringBuffer("");
            int len = breader.read(c_buf, 0, 8192);
            while (len > 0) {
                buf.append(c_buf, 0, len);
                c_buf = new char[8192];
                len = breader.read(c_buf, 0, 8192);
            }
            breader.close();
            return buf.toString();
        } catch (Exception e) {
            log.error("error in getHttpUrlContent " + urlStr, e);
        } finally {
            url = null;
            if (conn != null) {
                conn.disconnect();
            }
        }
        return "";
    }

    public static String getHttpUrlContent(String urlStr, String encoding,
            boolean isPost, String postBody) {
        return getHttpUrlContent(urlStr, encoding, isPost, postBody, null);
    }

    /**
     * 发送的是字节码，返回的也是字节码
     * 
     * @param urlStr
     * @param isPost
     * @param postBody
     * @return
     */
    public static byte[] getHttpUrlContent(String urlStr, boolean isPost,
            byte[] postBody, Map requestProperty) {
        URL url = null;
        HttpURLConnection conn = null;
        long startTime = System.currentTimeMillis();
        log.debug("get " + urlStr + "");
        try {
            url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            // 设置request header
            if (requestProperty != null) {
                for (Iterator it = requestProperty.keySet().iterator(); it
                        .hasNext();) {
                    String key = (String) it.next();
                    conn.setRequestProperty(key,
                            (String) requestProperty.get(key));
                }
            }
            log.info("whole url:"+url.toString());
            // conn.setInstanceFollowRedirects(false);
            // post方法
            if (isPost) {
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
            }
            // 设置连接超时和读取超时两个时间，防止被后台憋死
            conn.setConnectTimeout(3000);
            conn.setReadTimeout(3000);
            // 建立连接
            conn.connect();
            if (isPost) {
                OutputStream out = conn.getOutputStream();
                out.write(postBody);
            }
            InputStream is = conn.getInputStream();

            byte[] c_buf = new byte[8192];
            int len = is.read(c_buf, 0, 8192);
            byte[] result = new byte[0];
            int total = 0;
            while (len > 0) {
                total += len;
                byte[] old_result = result;
                result = new byte[total];
                if (old_result.length > 0) {
                    System.arraycopy(old_result, 0, result, 0, total - len);
                }
                System.arraycopy(c_buf, 0, result, total - len, len);
                len = is.read(c_buf, 0, 8192);
            }
            is.close();
            return result;
        } catch (Exception e) {
            log.error("error in getHttpUrlContent " + urlStr, e);
        } finally {
            url = null;
            // if(connState!=null){//减去并发连接数
            // synchronized (connState) {
            // if(connState.maxConns<=0){
            // log.error("error maxConns="+connState.maxConns+" for url="+urlPattern);
            // }else {
            // connState.maxConns--;
            // }
            // }
            // }
            // if(conn!=null){
            // conn.disconnect();
            // }
            long t = System.currentTimeMillis() - startTime;
            if (t > 300)
                log.warn(urlStr + " cost " + t);
        }
        return new byte[0];
    }

    private static class TrustAnyTrustManager implements X509TrustManager {

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    /**
     * 获得https的url返回内容
     * 
     * @param urlStr
     * @param encode
     * @return
     */
    public static String getHttpsContent(String urlStr, String encode,
            boolean isPost, String postBody) {
        String html = "";
        try {

            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },
                    new java.security.SecureRandom());
            URL url = new URL(urlStr);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            if (isPost) {
                conn.setRequestMethod("POST");
                conn.setDoOutput(true);
            } else {
                conn.setDoOutput(false);
            }
            conn.connect();

            // URL url = new URL(urlStr);
            // HttpsURLConnection conn =
            // (HttpsURLConnection)url.openConnection();
            // conn.setDoOutput(false);
            // conn.connect();
            if (isPost) {
                OutputStream out = conn.getOutputStream();
                out.write(postBody.getBytes(encode));
                out.flush();
                // BufferedWriter writer = new BufferedWriter(new
                // OutputStreamWriter(out,encoding));
                // writer.write(postBody);
                // writer.close();
            }
            InputStream is = null;
            try {
                is = conn.getInputStream();
            } catch (IOException ex) {
                is = conn.getErrorStream();
                ex.printStackTrace();
            }
            BufferedReader breader = new BufferedReader(new InputStreamReader(
                    is, encode));
            char[] c_buf = new char[8192];
            StringBuffer buf = new StringBuffer("");
            int len = breader.read(c_buf, 0, 8192);
            while (len > 0) {
                buf.append(c_buf, 0, len);
                c_buf = new char[8192];
                len = breader.read(c_buf, 0, 8192);
            }
            html = buf.toString();
            breader.close();
            is.close();
            conn.disconnect();
            conn = null;
            url = null;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return html;
    }

    public static String postFileWithParam(String url, String param, File f) {
        org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
        PostMethod method = new PostMethod(url);
        Part[] parts = new Part[1];
        try {
            parts[0] = new FilePart(param, f);
            MultipartRequestEntity entry = new MultipartRequestEntity(parts,
                    method.getParams());
            method.setRequestEntity(entry);
            client.executeMethod(method);
            String ret = new String(method.getResponseBody(),
                    method.getResponseCharSet());
            return ret;
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            method.releaseConnection();
        }
        return null;
    }

    /**
     * 上传文件的同时上传参数
     * 
     * @param url
     *            上传地址
     * @param filesMap
     *            参数名-File的map
     * @param strMap
     *            参数名-参数值的对象数组数组
     * @return
     * @throws IOException
     */
    public static String postFilesAndStrings(String url,
            Map<String, File> filesMap, Map<String, String> strMap)
            throws IOException {
        org.apache.commons.httpclient.HttpClient client = new org.apache.commons.httpclient.HttpClient();
        PostMethod method = new PostMethod(url);
        Part[] parts = new Part[filesMap.size() + strMap.size()];
        int index = 0;
        for (Iterator iterator = filesMap.entrySet().iterator(); iterator
                .hasNext();) {
            Entry<String, File> entry = (Entry<String, File>) iterator.next();
            parts[index++] = new FilePart(entry.getKey(), entry.getValue());
        }
        for (Iterator iterator = strMap.entrySet().iterator(); iterator
                .hasNext();) {
            Entry<String, String> entry = (Entry<String, String>) iterator
                    .next();
            parts[index++] = new StringPart(entry.getKey(), entry.getValue());
        }

        MultipartRequestEntity entry = new MultipartRequestEntity(parts,
                method.getParams());
        method.setRequestEntity(entry);
        String ret = null;
        try {
            client.executeMethod(method);
            ret = new String(method.getResponseBody(),
                    method.getResponseCharSet());
        } catch (HttpException e) {
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            method.releaseConnection();
        }
        return ret;
    }

    // public String
    // string agent = request.getheader("user-agent");
    // stringtokenizer st = new stringtokenizer(agent,";");
    // st.nexttoken();
    // //得到用户的浏览器名
    // string userbrowser = st.nexttoken();

    public static void main(String[] args) {
        String serverUrl = "https://api.weibo.com/2/statuses/update.json";
        Map<String, String> headMap = new HashMap<String, String>();
        headMap.put("status", "3dfasdfdasfadsfdasf33");
        headMap.put("client_appkey", "858239903");
        headMap.put("visible", "0");
        headMap.put("access_token", "2.00co_CnD0F6FFwa37b531a8foOoSkB");
        String postbody = "client_appkey=858239903&status=3dfasdfdasfadsfdasf33&visible=0&access_token=2.00co_CnD0F6FFwa37b531a8foOoSkB";
        String s = getHttpUrlContent(serverUrl, "utf8", true, postbody, null);
        // String urlStr, String encoding, boolean isPost, String postBody, Map
        // requestProperty
        System.out.println(s);

    }
    // static class ConnectionState {
    // public int maxConns = 1;
    // public int total=1;
    // }
}
